﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using CTS.Com.Domain.Constants;
using CTS.Com.Domain.Helper;
using CTS.Data.Domain.Constants;
using CTS.Data.Domain.Enum;

namespace CTS.Data.Domain.Helper
{
    /// <summary>
    /// DaoHelper
    /// </summary>
    public static class DaoHelper
    {
        /// <summary>
        /// Chuyển đổi dữ liệu khi thực thi sql
        /// </summary>
        /// <param name="source">Đối tượng nguồn</param>
        /// <returns>Đối tượng đã chuyển đổi</returns>
        public static object ToSqlData(object source)
        {
            // Trường hợp đối tượng nguồn là 'Null'
            if (source == null) {
                return string.Empty;
            }
            // Khợi tạo biến cục bộ
            var rObj = new object();
            var type = source.GetType();
            if (type == typeof(bool?)) {
                var tmp = (bool?)source;
                if (tmp.HasValue) {
                    rObj = tmp.Value ? DataLogics.DB_BIT_TRUE : DataLogics.DB_BIT_FALSE;
                } else {
                    rObj = string.Empty;
                }
            } else if (type == typeof(string[])) {
                var tmp = (string[])source;
                rObj = DataHelper.JoinStringArray(tmp, Logics.DELIMITER_COMMA);
            } else if (type.Namespace == "System.Collections.Generic") {
                var tmp = (IList)source;
                rObj = DataHelper.JoinStringList(tmp, Logics.DELIMITER_COMMA);
            } else {
                rObj = source;
            }
            // Kết quả trả về
            return rObj;
        }

        private static bool Compare(object obj1, object obj2, CompareType cpt)
        {
            // Variable initialize
            var result = false;
            // Check null
            if (obj1 == null || obj2 == null) {
                return result;
            }
            // Get type
            var type1 = obj1.GetType();
            var type2 = obj2.GetType();
            // Check valid (decimal, dateTime)
            if (type1 != typeof(decimal) && type1 != typeof(DateTime)) {
                return result;
            }
            // Check valid (type1, type2)
            if ((type1 == typeof(decimal) && type2 != typeof(decimal))
                || (type1 == typeof(DateTime) && type2 != typeof(DateTime))) {
                return result;
            }
            // Decimal
            if (type1 == typeof(decimal)) {
                // Get value
                var num1 = Convert.ToDecimal(obj1);
                var num2 = Convert.ToDecimal(obj2);
                // Compare
                switch (cpt) {
                    case CompareType.Li:
                        result = num1 < num2;
                        break;
                    case CompareType.Le:
                        result = num1 <= num2;
                        break;
                    case CompareType.Gt:
                        result = num1 > num2;
                        break;
                    case CompareType.Ge:
                        result = num1 >= num2;
                        break;
                }
            }
            // DateTime
            if (type1 == typeof(DateTime)) {
                // Get value
                var date1 = Convert.ToDateTime(obj1);
                var date2 = Convert.ToDateTime(obj2);
                // Compare
                switch (cpt) {
                    case CompareType.Li:
                        result = date1 < date2;
                        break;
                    case CompareType.Le:
                        result = date1 <= date2;
                        break;
                    case CompareType.Gt:
                        result = date1 > date2;
                        break;
                    case CompareType.Ge:
                        result = date1 >= date2;
                        break;
                }
            }
            // Return value
            return result;
        }

        /// <summary>
        /// Equal
        /// </summary>
        /// <param name="obj1">Object</param>
        /// <param name="obj2">Object</param>
        /// <returns>True/False</returns>
        public static bool Eq(object obj1, object obj2)
        {
            // Return value
            return obj1 == obj2;
        }

        /// <summary>
        /// Not equal
        /// </summary>
        /// <param name="obj1">Object</param>
        /// <param name="obj2">Object</param>
        /// <returns>True/False</returns>
        public static bool Ne(object obj1, object obj2)
        {
            // Return value
            return obj1 != obj2;
        }

        /// <summary>
        /// Little
        /// </summary>
        /// <param name="obj1">Object</param>
        /// <param name="obj2">Object</param>
        /// <returns>True/False</returns>
        public static bool Li(object obj1, object obj2)
        {
            // Return value
            return Compare(obj1, obj2, CompareType.Li);
        }

        /// <summary>
        /// Little equal
        /// </summary>
        /// <param name="obj1">Object</param>
        /// <param name="obj2">Object</param>
        /// <returns>True/False</returns>
        public static bool Le(object obj1, object obj2)
        {
            // Return value
            return Compare(obj1, obj2, CompareType.Le);
        }

        /// <summary>
        /// Great
        /// </summary>
        /// <param name="obj1">Object</param>
        /// <param name="obj2">Object</param>
        /// <returns>True/False</returns>
        public static bool Gt(object obj1, object obj2)
        {
            // Return value
            return Compare(obj1, obj2, CompareType.Gt);
        }

        /// <summary>
        /// Great equal
        /// </summary>
        /// <param name="obj1">Object</param>
        /// <param name="obj2">Object</param>
        /// <returns>True/False</returns>
        public static bool Ge(object obj1, object obj2)
        {
            // Return value
            return Compare(obj1, obj2, CompareType.Ge);
        }

        /// <summary>
        /// In
        /// </summary>
        /// <param name="list">List</param>
        /// <param name="obj">Object</param>
        /// <returns>True/False</returns>
        public static bool In(IList list, object obj)
        {
            // Check null
            if (list == null || list.Count <= 0) {
                return false;
            }
            // Return value
            return list.Contains(obj);
        }

        /// <summary>
        /// In with func
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="list">List</param>
        /// <param name="obj">Object</param>
        /// <param name="func">Func<T, Object></param>
        /// <returns>True/False</returns>
        public static bool In<T>(IList<T> list, object obj, Func<T, object> func)
        {
            // Check null
            if (list == null || list.Count <= 0) {
                return false;
            }
            // Get list object
            var lstObject = list.Select(func).ToList();
            // Return value
            return In(lstObject, obj);
        }

        /// <summary>
        /// Not in
        /// </summary>
        /// <param name="list">List</param>
        /// <param name="obj">Object</param>
        /// <returns>True/False</returns>
        public static bool NotIn(IList list, object obj)
        {
            // Return value
            return In(list, obj) == false;
        }

        /// <summary>
        /// Not in with func
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="list">List</param>
        /// <param name="obj">Object</param>
        /// <param name="func">Func<T, Object></param>
        /// <returns>True/False</returns>
        public static bool NotIn<T>(IList<T> list, object obj, Func<T, object> func)
        {
            // Return value
            return In(list, obj, func) == false;
        }

        /// <summary>
        /// Like
        /// </summary>
        /// <param name="str1">String</param>
        /// <param name="str2">String</param>
        /// <returns>True/False</returns>
        public static bool Like(string str1, string str2)
        {
            return str1.Contains(str2);
        }

        /// <summary>
        /// Not like
        /// </summary>
        /// <param name="str1">String</param>
        /// <param name="str2">String</param>
        /// <returns>True/False</returns>
        public static bool NotLike(string str1, string str2)
        {
            return Like(str1, str2) == false;
        }

        /// <summary>
        /// Start
        /// </summary>
        /// <param name="str1">String</param>
        /// <param name="str2">String</param>
        /// <returns>True/False</returns>
        public static bool Start(string str1, string str2)
        {
            return str1.StartsWith(str2);
        }

        /// <summary>
        /// Not start
        /// </summary>
        /// <param name="str1">String</param>
        /// <param name="str2">String</param>
        /// <returns>True/False</returns>
        public static bool NotStart(string str1, string str2)
        {
            return Start(str1, str2) == false;
        }

        /// <summary>
        /// End
        /// </summary>
        /// <param name="str1">String</param>
        /// <param name="str2">String</param>
        /// <returns>True/False</returns>
        public static bool End(string str1, string str2)
        {
            return str1.EndsWith(str2);
        }

        /// <summary>
        /// Not end
        /// </summary>
        /// <param name="str1">String</param>
        /// <param name="str2">String</param>
        /// <returns>True/False</returns>
        public static bool NotEnd(string str1, string str2)
        {
            return End(str1, str2) == false;
        }

        /// <summary>
        /// Is null
        /// </summary>
        /// <param name="obj">Object</param>
        /// <returns>True/False</returns>
        public static bool IsNull(object obj)
        {
            // Chech null
            if (obj == null) {
                return true;
            }
            // Get type
            var type = obj.GetType();
            // String
            if (type == typeof(string)) {
                // Get Value
                var str = Convert.ToString(obj).Trim();
                // Check empty
                if (str == string.Empty) {
                    return true;
                }
            }
            // Return value
            return false;
        }

        /// <summary>
        /// Is not null
        /// </summary>
        /// <param name="obj">Object</param>
        /// <returns>True/False</returns>
        public static bool IsNotNull(object obj)
        {
            // Return value
            return IsNull(obj) == false;
        }
    }
}
